import { Tile } from "./tile";

export class Grid {
  _row_size: number = 7;
  _col_size: number = 10;
  cells: any[][] = [[]]; //二维数组
  constructor(previousState?: any) {
    this.cells = previousState ? this.fromState(previousState) : this.randomCells();
  }

  randomCells() {
    // 共10种卡片,5种重复6次,5种重复8次
    // 先创建包含 10 种卡片的数组
    const allCardTypes = Array.from({ length: 10 }, (_, i) => `icon${i + 1}`);
    // 打乱卡片顺序
    for (let i = allCardTypes.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [allCardTypes[i], allCardTypes[j]] = [allCardTypes[j], allCardTypes[i]];
    }
    const cardTypes: any = [];
    // 随机选取的前 5 种卡片重复 6 次
    for (let i = 0; i < 5; i++) {
      for (let j = 0; j < 6; j++) {
        cardTypes.push(allCardTypes[i]);
      }
    }
    // 随机选取的后 5 种卡片重复 8 次
    for (let i = 5; i < 10; i++) {
      for (let j = 0; j < 8; j++) {
        cardTypes.push(allCardTypes[i]);
      }
    }

    // 再次打乱最终卡片数组的顺序
    for (let i = cardTypes.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [cardTypes[i], cardTypes[j]] = [cardTypes[j], cardTypes[i]];
    }
    console.log(cardTypes);

    const cells = [];
    let index = 0;
    /*
[[{x:0,y:0},{x:0,y:1},{x:0,y:2},{x:0,y:3}],
[{x:1,y:0},{x:1,y:1},{x:1,y:2},{x:1,y:3}],
[{x:2,y:0},{x:2,y:1},{x:2,y:2},{x:2,y:3}],
[{x:3,y:0},{x:3,y:1},{x:3,y:2},{x:3,y:3}]]
*/
    for (let x = 0; x < this._row_size; x++) {
      const row: any = cells[x] = [];
      for (let y = 0; y < this._col_size; y++) {
        if (index < cardTypes.length) {
          const tile = new Tile({ x, y }, cardTypes[index], false);
          row.push(tile);
          index++;
        } else {
          // 如果卡片用完，剩余位置设为 null
          row.push(null);
        }
      }
    }
    return cells;
  }

  fromState(state: any[][]) {
    const cells = [];

    for (let x = 0; x < this._row_size; x++) {
      const row: any = cells[x] = [];

      for (let y = 0; y < this._col_size; y++) {
        const tile = state[x][y];
        row.push(tile ? new Tile(tile.position, tile.value, tile.isOnBound) : null);
      }
    }

    return cells;
  }
  // 返回所有未消除单元格
  occupiedCells() {
    const cells: any[] = [];

    this.eachCell((x: any, y: any, tile: any) => {
      if (tile) {
        // 返回没有被占用的砖块坐标
        cells.push({ x, y });
      }
    });

    return cells;
  }

  // 遍历获取size边界内所有单元格
  eachCell(callback: { (x: any, y: any, tile: any): void; (arg0: number, arg1: number, arg2: never): void; }) {
    for (let x = 0; x < this._row_size; x++) {
      for (let y = 0; y < this._col_size; y++) {
        callback(x, y, this.cells[x][y]);
      }
    }
  }

  // 获取剩下未被消除的单元格数量
  getLeftTileNum() {
    return this.occupiedCells().length;
  }


  // 检查单元格是否被占领-未消除
  cellOccupied(cell: any) {
    return !!this.cellContent(cell);
  }

  // 获取单元格内容
  cellContent(cell: { x: number; y: number; }) {
    if (this.withinBounds(cell)) {
      return this.cells[cell.x][cell.y];
    } else {
      return null;
    }
  }
  // 基于当前未消除方块, 重置方块内容
  resetCells() {

  }

  // Inserts a tile at its position
  insertTile(tile: { x: number; y: number; }) {
    this.cells[tile.x][tile.y] = tile;
  }

  removeTile(tile: { x: number; y: number; }) {
    this.cells[tile.x][tile.y] = null;
  }

  // 检查元素是否在网格矩阵中row*col
  withinBounds(position: { x: any; y: any; }) {
    return position.x >= 0 && position.x < this._row_size &&
      position.y >= 0 && position.y < this._col_size;
  }
  isOnBoundary(position: { x: number; y: number; }): boolean {
    if (!this.withinBounds(position)) {
      return false; // 如果位置不在网格内，直接返回 false
    }
    return position.x === 0 || position.x === this._row_size - 1 ||
           position.y === 0 || position.y === this._col_size - 1;
  }

  serialize() {
    const cellState = [];
    let left_tile_num = 0;

    for (let x = 0; x < this._row_size; x++) {
      const row: any = cellState[x] = [];

      for (let y = 0; y < this._col_size; y++) {
        if (this.cells[x][y]) {
          left_tile_num++;
          row.push(this.cells[x][y].serialize())
        } else {
          row.push(null);
        }
      }
    }

    return {
      total: this._row_size * this._col_size,
      left_tile_num,
      cells: cellState
    };
  }
}